package com.springboot.frame.mapper.provider;

import com.springboot.frame.Condition;
import com.springboot.frame.schema.Column;
import com.springboot.frame.schema.LogicColumn;
import com.springboot.frame.schema.PrimaryKey;
import com.springboot.frame.schema.Table;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.builder.annotation.ProviderContext;
import org.apache.ibatis.jdbc.SQL;
import java.io.Serializable;
import java.util.Collection;

/**
 * SQL查询处理类
 *
 * @author liheng
 */
@Slf4j
public final class SelectMapperProvider extends AbstractMapperProvider {

    private static final String COUNT_1 = "count(1)";

    /**
     * 根据id查询
     *
     * @param id
     * @param providerContext
     * @return
     */
    public String selectById(Object id, ProviderContext providerContext) {
        Table table = getTable(providerContext);
        SQL sql = new SQL().SELECT(table.getSelectBody()).FROM(table.getTableName());
        PrimaryKey primaryKey = table.getPrimaryKey();
        String primaryKeyColumnName = primaryKey.getColumnName();
        if (id == null) {
            sql.WHERE(primaryKeyColumnName + " IS NULL");
        } else {
            sql.WHERE(primaryKeyColumnName + " = #{" + primaryKey.getPropertyName() + "}");
        }
        // 逻辑删除
        LogicColumn logicColumn = table.getLogicColumn();
        if (logicColumn != null) {
            sql.WHERE(logicColumn.getColumnName() + "=" + logicColumn.getValue());
        }
        return sql.toString();
    }

    /**
     * 根据id批量查询
     *
     * @param params
     * @param providerContext
     * @return
     */
    public String selectBatchIds(@Param("list") Collection<Serializable> params,
                                 ProviderContext providerContext) {
        if (CollectionUtils.isEmpty(params)) {
            return this.selectById(null, providerContext);
        }
        Table table = getTable(providerContext);
        StringBuilder ids = new StringBuilder(params.size());
        for (int i = 0; i < params.size(); i++) {
            ids.append("#{list[" + i + "]},");
        }
        SQL sql = new SQL().SELECT(table.getSelectBody()).FROM(table.getTableName())
                .WHERE(table.getPrimaryKey().getColumnName() + " in (" + ids.deleteCharAt(ids.length() - 1)
                        + ")");
        // 逻辑删除
        LogicColumn logicColumn = table.getLogicColumn();
        if (logicColumn != null) {
            sql.WHERE(logicColumn.getColumnName() + "=" + logicColumn.getValue());
        }
        return sql.toString();
    }

    /**
     * 查询记录数
     *
     * @param condition
     * @param providerContext
     * @return
     * @throws IllegalAccessException
     */
    public String selectCount(Condition<?> condition, ProviderContext providerContext)
            throws IllegalAccessException {
        Table table = getTable(providerContext);
        if (condition == null) {
            SQL sql = new SQL().SELECT(COUNT_1).FROM(table.getTableName());
            // 逻辑删除
            LogicColumn logicColumn = table.getLogicColumn();
            if (logicColumn != null) {
                sql.WHERE(logicColumn.getColumnName() + "=" + logicColumn.getValue());
            }
            return sql.toString();
        }
        return getSql(condition, table,
                StringUtils.isNotBlank(condition.getSelectBody()) ? condition.getSelectBody() : COUNT_1);
    }

    /**
     * 查询集合
     *
     * @param condition
     * @param providerContext
     * @return
     * @throws IllegalAccessException
     */
    public String selectList(Condition<?> condition, ProviderContext providerContext)
            throws IllegalAccessException {
        Table table = getTable(providerContext);
        if (condition == null) {
            SQL sql = new SQL().SELECT(table.getSelectBody()).FROM(table.getTableName());
            // 逻辑删除
            LogicColumn logicColumn = table.getLogicColumn();
            if (logicColumn != null) {
                sql.WHERE(logicColumn.getColumnName() + "=" + logicColumn.getValue());
            }
            return sql.toString();
        }
        return getSql(condition, table,
                StringUtils.isNotBlank(condition.getSelectBody()) ? condition.getSelectBody()
                        : table.getSelectBody());
    }


    /**
     * 根据参数对象，表信息，查询内容，构造sql语句
     *
     * @param condition
     * @param info
     * @param selectBody
     * @return
     * @throws IllegalAccessException
     */
    private String getSql(Condition<?> condition, Table info, String selectBody)
            throws IllegalAccessException {
        SQL sql = new SQL().FROM(info.getTableName());
        // 检查参数对象是否为空
        Object parameterObject = condition.getParameterObject();
        if (parameterObject != null) {
            PrimaryKey primaryKey = info.getPrimaryKey();
            // 增加主键约束，主键参数属性不为空的情况
            if (primaryKey != null && primaryKey.getField().get(parameterObject) != null) {
                sql.WHERE(primaryKey.getColumnName() + "=#{parameterObject." + primaryKey.getPropertyName()
                        + "}");
            }
            // 增加参数对象条件约束，对象属性不为空的情况
            for (Column column : info.getColumns()) {
                if (column.getField().get(parameterObject) != null) {
                    sql.WHERE(
                            column.getColumnName() + "=#{parameterObject." + column.getPropertyName() + "}");
                }
            }
        }
        // 是否去重
        if (condition.isDistinct()) {
            sql.SELECT_DISTINCT(selectBody);
        } else {
            sql.SELECT(selectBody);
        }
        // 如果条件不为空，拼接条件
        if (CollectionUtils.isNotEmpty(condition.getWhere())) {
            // 拼接sql条件 sql.WHERE(condition.getWhere().toArray(new String[condition.getWhere().size()]));  对书写方法不友好
            sql.WHERE(StringUtils.join(condition.getWhere(), separator));
        }
        // 追加逻辑删除
        LogicColumn logicColumn = info.getLogicColumn();
        if (logicColumn != null && condition.isLogicDelete()) {
            sql.WHERE(logicColumn.getColumnName() + "=" + logicColumn.getValue());
        }
        // 追加分组
        if (CollectionUtils.isNotEmpty(condition.getGroupBy())) {
            sql.GROUP_BY(condition.getGroupBy().toArray(new String[condition.getGroupBy().size()]));
        }
        // 追加排序
        if (CollectionUtils.isNotEmpty(condition.getOrderBy())) {
            sql.ORDER_BY(condition.getOrderBy().toArray(new String[condition.getOrderBy().size()]));
        }
        // 追加分页
        if (StringUtils.isNotBlank(condition.getLimit())) {
            sql.toString();
            // 追加分页
            StringBuilder sb = new StringBuilder();
            sb.append(sql.toString()).append(separator).append(condition.getLimit());
            return sb.toString();
        }
        return sql.toString();
    }
}
